www.gusucode.com > VC++ 特殊网址访问器源代码-源码程序 > VC++ 特殊网址访问器源代码-源码程序/code/Demo3/SaveScrJpg.cpp
//Download by http://www.NewXing.com // SaveScrJpg.cpp: implementation of the SaveScrJpg class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "SaveScrJpg.h" #include "math.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// HANDLE SaveScrJpg::DDBToDIB( HBITMAP hBitmap, DWORD dwCompression, HPALETTE hPal ) { BITMAP bm; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; DWORD dwLen; HANDLE hDIB; HANDLE handle; HDC hDC; ASSERT( hBitmap ); // The function has no arg for bitfields if( dwCompression == BI_BITFIELDS ) return NULL; // If a palette has not been supplied use defaul palette if (hPal==NULL) hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE); // Get bitmap information ::GetObject(hBitmap,sizeof(bm),(LPSTR)&bm); // Initialize the bitmapinfoheader bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bm.bmWidth; bi.biHeight = bm.bmHeight; bi.biPlanes = 1; bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel; bi.biCompression = dwCompression; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; // Compute the size of the infoheader and the color table int nColors = (1 << bi.biBitCount); if( nColors > 256 ) nColors = 0; dwLen = bi.biSize + nColors * sizeof(RGBQUAD); // We need a device context to get the DIB from hDC = GetDC(NULL); hPal = SelectPalette(hDC,hPal,FALSE); RealizePalette(hDC); // Allocate enough memory to hold bitmapinfoheader and color table hDIB = GlobalAlloc(GMEM_FIXED,dwLen); if (!hDIB){ SelectPalette(hDC,hPal,FALSE); ReleaseDC(NULL,hDC); return NULL; } lpbi = (LPBITMAPINFOHEADER)hDIB; *lpbi = bi; // Call GetDIBits with a NULL lpBits param, so the device driver // will calculate the biSizeImage field GetDIBits(hDC, hBitmap, 0L, (DWORD)bi.biHeight, (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS); bi = *lpbi; // If the driver did not fill in the biSizeImage field, then compute it // Each scan line of the image is aligned on a DWORD (32bit) boundary if (bi.biSizeImage == 0){ bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight; // If a compression scheme is used the result may infact be larger // Increase the size to account for this. if (dwCompression != BI_RGB) bi.biSizeImage = (bi.biSizeImage * 3) / 2; } // Realloc the buffer so that it can hold all the bits dwLen += bi.biSizeImage; if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE)) hDIB = handle; else{ GlobalFree(hDIB); // Reselect the original palette SelectPalette(hDC,hPal,FALSE); ReleaseDC(NULL,hDC); return NULL; } // Get the bitmap bits lpbi = (LPBITMAPINFOHEADER)hDIB; // FINALLY get the DIB BOOL bGotBits = GetDIBits( hDC, hBitmap, 0L, // Start scan line (DWORD)bi.biHeight, // # of scan lines (LPBYTE)lpbi // address for bitmap bits + (bi.biSize + nColors * sizeof(RGBQUAD)), (LPBITMAPINFO)lpbi, // address of bitmapinfo (DWORD)DIB_RGB_COLORS); // Use RGB for color table if( !bGotBits ) { GlobalFree(hDIB); SelectPalette(hDC,hPal,FALSE); ReleaseDC(NULL,hDC); return NULL; } SelectPalette(hDC,hPal,FALSE); ReleaseDC(NULL,hDC); return hDIB; } ////////////////////////////////////////////////////////////////////// BOOL SaveScrJpg::JpegFromDib(HANDLE hDib, //Handle to DIB int nQuality, //JPEG quality (0-100) CString csJpeg, //Pathname to jpeg file CString* pcsMsg) //Error msg to return { //Basic sanity checks... if (nQuality < 0 || nQuality > 100 || hDib == NULL || pcsMsg == NULL || csJpeg == "") { if (pcsMsg != NULL) *pcsMsg = "Invalid input data"; return FALSE; } *pcsMsg = ""; LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDib; // BYTE *buf2 = 0; //Use libjpeg functions to write scanlines to disk in JPEG format struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; FILE* pOutFile; //Target file int nSampsPerRow; //Physical row width in image buffer JSAMPARRAY jsmpArray; //Pixel RGB buffer for JPEG file cinfo.err = jpeg_std_error(&jerr); //Use default error handling (ugly!) jpeg_create_compress(&cinfo); if ((pOutFile = fopen(csJpeg, "wb")) == NULL) { *pcsMsg = "Cannot open "; *pcsMsg += csJpeg; jpeg_destroy_compress(&cinfo); return FALSE; } jpeg_stdio_dest(&cinfo, pOutFile); cinfo.image_width = lpbi->biWidth; //Image width and height, in pixels cinfo.image_height = lpbi->biHeight; cinfo.input_components = 3; //Color components per pixel //(RGB_PIXELSIZE - see jmorecfg.h) cinfo.in_color_space = JCS_RGB; //Colorspace of input image jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, nQuality, //Quality: 0-100 scale TRUE); //Limit to baseline-JPEG values jpeg_start_compress(&cinfo, TRUE); //JSAMPLEs per row in output buffer nSampsPerRow = cinfo.image_width * cinfo.input_components; //Allocate array of pixel RGB values jsmpArray = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, nSampsPerRow, cinfo.image_height); if (DibToSamps(hDib, nSampsPerRow, cinfo, jsmpArray, pcsMsg)) { //Write the array of scan lines to the JPEG file (void)jpeg_write_scanlines(&cinfo, jsmpArray, cinfo.image_height); } jpeg_finish_compress(&cinfo); //Always finish rewind(pOutFile);/**/ fputc(0x00,pOutFile); fputc(0x00,pOutFile); fclose(pOutFile); jpeg_destroy_compress(&cinfo); //Free resources if (*pcsMsg != "") return FALSE; else return TRUE; } ////////////////////////////////////////////////////////////////////// //This function fills a jsmpArray with the RGB values for the CBitmap. //It has been improved to handle all legal bitmap formats. //A jsmpArray is a big array of RGB values, 3 bytes per value. //Note that rows of pixels are processed bottom to top: //The data in the jsamp array must be arranged top to bottom. ////////////////////////////////////////////////////////////////////// BOOL SaveScrJpg::DibToSamps(HANDLE hDib, int nSampsPerRow, struct jpeg_compress_struct cinfo, JSAMPARRAY jsmpPixels, CString* pcsMsg) { //Sanity... if (hDib == NULL || nSampsPerRow <= 0 || pcsMsg == NULL) { if (pcsMsg !=NULL) *pcsMsg="Invalid input data"; return FALSE; } int r=0, p=0, q=0, b=0, n=0, nUnused=0, nBytesWide=0, nUsed=0, nLastBits=0, nLastNibs=0, nCTEntries=0, nRow=0, nByte=0, nPixel=0; BYTE bytCTEnt=0; LPBITMAPINFOHEADER pbBmHdr= (LPBITMAPINFOHEADER)hDib; //The bit count tells you the format of the bitmap: //Decide how many entries will be in the color table (if any) switch (pbBmHdr->biBitCount) { case 1: nCTEntries = 2; //Monochrome break; case 4: nCTEntries = 16; //16-color break; case 8: nCTEntries = 256; //256-color break; case 16: case 24: case 32: nCTEntries = 0; //No color table needed break; default: *pcsMsg = "Invalid bitmap bit count"; return FALSE; //Unsupported format } //Point to the color table and pixels DWORD dwCTab = (DWORD)pbBmHdr + pbBmHdr->biSize; LPRGBQUAD pCTab = (LPRGBQUAD)(dwCTab); LPSTR lpBits = (LPSTR)pbBmHdr + (WORD)pbBmHdr->biSize + (WORD)(nCTEntries * sizeof(RGBQUAD)); //Different formats for the image bits LPBYTE lpPixels = (LPBYTE) lpBits; RGBQUAD* pRgbQs = (RGBQUAD*)lpBits; WORD* wPixels = (WORD*) lpBits; //Set up the jsamps according to the bitmap's format. //Note that rows are processed bottom to top, because //that's how bitmaps are created. switch (pbBmHdr->biBitCount) { case 1: nUsed = (pbBmHdr->biWidth + 7) / 8; nUnused = (((nUsed + 3) / 4) * 4) - nUsed; nBytesWide = nUsed + nUnused; nLastBits = 8 - ((nUsed * 8) - pbBmHdr->biWidth); for (r=0; r < pbBmHdr->biHeight; r++) { for (p=0,q=0; p < nUsed; p++) { nRow=(pbBmHdr->biHeight-r-1) * nBytesWide; nByte = nRow + p; int nBUsed = (p <(nUsed - 1)) ? 8 : nLastBits; for(b=0; b < nBUsed; b++) { bytCTEnt = lpPixels[nByte] << b; bytCTEnt = bytCTEnt >> 7; jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed; jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen; jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue; q += 3; } } } break; case 4: nUsed = (pbBmHdr->biWidth + 1) / 2; nUnused = (((nUsed + 3) / 4) * 4) - nUsed; nBytesWide = nUsed + nUnused; nLastNibs = 2 - ((nUsed * 2) - pbBmHdr->biWidth); for (r=0; r < pbBmHdr->biHeight;r++) { for (p=0,q=0; p < nUsed;p++) { nRow=(pbBmHdr->biHeight-r-1) * nBytesWide; nByte = nRow + p; jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed; jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen; jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue; q += 3; } } break; case 8: //Each byte is a pointer to a pixel color nUnused = (((pbBmHdr->biWidth + 3) / 4) * 4) - pbBmHdr->biWidth; for (r=0;r < pbBmHdr->biHeight; r++) { for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3) { nRow = (pbBmHdr->biHeight-r-1) * (pbBmHdr->biWidth + nUnused); nPixel = nRow + p; jsmpPixels[r][q+0] = pCTab[lpPixels[nPixel]].rgbRed; jsmpPixels[r][q+1] = pCTab[lpPixels[nPixel]].rgbGreen; jsmpPixels[r][q+2] = pCTab[lpPixels[nPixel]].rgbBlue; } } break; case 16: //Hi-color (16 bits per pixel) for (r=0;r < pbBmHdr->biHeight; r++) { for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3) { nRow = (pbBmHdr->biHeight-r-1) * pbBmHdr->biWidth; nPixel = nRow + p; RGBQUAD quad = QuadFromWord(wPixels[nPixel]); jsmpPixels[r][q+0] = quad.rgbRed; jsmpPixels[r][q+1] = quad.rgbGreen; jsmpPixels[r][q+2] = quad.rgbBlue; } } break; case 24: nBytesWide = (pbBmHdr->biWidth*3); nUnused = (((nBytesWide + 3) / 4) * 4) - nBytesWide; nBytesWide += nUnused; for (r=0;r<pbBmHdr->biHeight;r++) { for (p=0,q=0;p < (nBytesWide-nUnused); p+=3,q+=3) { nRow = (pbBmHdr->biHeight-r-1) * nBytesWide; nPixel = nRow + p; jsmpPixels[r][q+0] = lpPixels[nPixel+2]; //Red jsmpPixels[r][q+1] = lpPixels[nPixel+1]; //Green jsmpPixels[r][q+2] = lpPixels[nPixel+0]; //Blue } } break; case 32: for (r=0; r < pbBmHdr->biHeight; r++) { for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3) { nRow = (pbBmHdr->biHeight-r-1) * pbBmHdr->biWidth; nPixel = nRow + p; jsmpPixels[r][q+0] = pRgbQs[nPixel].rgbRed; jsmpPixels[r][q+1] = pRgbQs[nPixel].rgbGreen; jsmpPixels[r][q+2] = pRgbQs[nPixel].rgbBlue; } } break; } //end switch return TRUE; } ////////////////////////////////////////////////////////////////////// //This function turns a 16-bit pixel //into an RGBQUAD value. ////////////////////////////////////////////////////////////////////// RGBQUAD SaveScrJpg::QuadFromWord(WORD b16) { BYTE bytVals[] = { 0, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104,112,120,128, 136,144,152,160,168,176,184,192, 200,208,216,224,232,240,248,255 }; WORD wR = b16; WORD wG = b16; WORD wB = b16; wR <<= 1; wR >>= 11; wG <<= 6; wG >>= 11; wB <<= 11; wB >>= 11; RGBQUAD rgb; rgb.rgbReserved = 0; rgb.rgbBlue = bytVals[wB]; rgb.rgbGreen = bytVals[wG]; rgb.rgbRed = bytVals[wR]; return rgb; } ////////////////////////////////////////////////////////////////////// SaveScrJpg::SaveScrJpg() { strcpy(SaveAddr,"C:" ); } ////////////////////////////////////////////////////////////////////// SaveScrJpg::~SaveScrJpg() { } ////////////////////////////////////////////////////////////////////// void SaveScrJpg::SaveScreen(int jpgOrder) { HDC hScrDC, hMemDC; HBITMAP hBitmap, hOldBitmap; int nX, nY, nX2, nY2; int nWidth, nHeight; int xScrn, yScrn; CString one; hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); hMemDC = CreateCompatibleDC(hScrDC); nX = 0; nY = 0; nX2 =GetDeviceCaps(hScrDC, HORZRES); nY2 =GetDeviceCaps(hScrDC, VERTRES); /// get screen resolution xScrn =GetDeviceCaps(hScrDC, HORZRES); yScrn =GetDeviceCaps(hScrDC, VERTRES); //make sure bitmap rectangle is visible if (nX < 0) nX = 0; if (nY < 0) nY = 0; if (nX2 > xScrn) nX2 = xScrn; if (nY2 > yScrn) nY2 = yScrn; nWidth = nX2 - nX; nHeight = nY2 - nY; // create a bitmap compatible with the screen DC hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); hOldBitmap =(HBITMAP) SelectObject(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); HANDLE hDib=DDBToDIB( hBitmap, BI_RGB, NULL); CString csMsg = ""; CString RealSaveName; RealSaveName.Format("%s\\%d.jpg",SaveAddr,jpgOrder); if (hDib != NULL) { if (!JpegFromDib(hDib, 45, //画面质量 0-100 RealSaveName,&csMsg)) ::MessageBox(NULL,csMsg,NULL,MB_OK); else ::GlobalFree(hDib); } else ::MessageBox(NULL,"Failed to load IDB_TEST",NULL,MB_OK); ::SelectObject(hMemDC,hOldBitmap); ::DeleteObject(hBitmap); ::DeleteDC(hScrDC); ::DeleteDC(hMemDC); } //////////////////////////////////////////////////////////////////////